package model.scaling;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import model.IObservable;
import model.auxillary.Parameter;
import model.auxillary.ParameterCollectionScaling;
import model.auxillary.ParameterListScaling;
import model.auxillary.ParameterListScaling.ParameterType;
import view.IObserver;

//#Neu
/**
 * A {@code Scaling} is the most abstract version to model a facility, factory, 
 * company, location, an industrial sector or a product. It can be observed by 
 * observers. It also has the role of an observer. It observes the scalings' 
 * parameters.
 * @author Sebastian Perlwitz
 *
 */
public abstract class Scaling implements IObservable, IObserver {
	
	/**
	 * The name of this scaling.
	 */
	protected String name;
	
	/**
	 * An identifying id for this Scaling.
	 */
	protected String id;
	
	/**
	 * The observers of Scaling.
	 */
	protected Collection<IObserver> observers;
	
	/**
	 * The scalings' parameters handled by a {@code ParameterListScaling} object.
	 */
	protected ParameterListScaling parameters;
	
	/**
	 * To indicate whether the calculation of this {@code Facility} caused an
	 * error. {@code true} when calculation caused an error, {@code false}
	 * otherwise.
	 */
	protected boolean error;
	
	/**
	 * To indicate that the calculation was aborted. This does not always
	 * mean that an error occurred. {@code true} when calculation was aborted,
	 * {@code false} otherwise.
	 */
	protected boolean aborted;
	
	/**
	 * To create a new {@code Scaling}.
	 * @param name the name of scaling.
	 * @param id a unique ID that identifies this scaling.
	 */
	public Scaling(String name, String id) {
		this.name = name;
		this.id = id;
		error = false;
		observers = new ArrayList<IObserver>();
		parameters = new ParameterListScaling(this);
	}
	
	/**
	 * To set a name for this {@code Scaling}.
	 * @param name the new name to be set.
	 */
	public void setName(String name) {		
		this.name = name;
		notifyObservers();
	}
	
	/**
	 * To get the name of this {@code Scaling}.
	 * @return The name.
	 */
	public String getName() {
		return name;
	}
	
	/**
	 * To get the unique ID of this {@code Scaling}.
	 * @return The unique ID.
	 */
    public String getID() {
    	return id;
    }
   
	/**
	 * Whether all parameters that have to be set by the user are set or not.
	 * @return <b>{@code true}</b> when all parameters are set, 
	 * <b>{@code false}</b> otherwise.
	 */
	public boolean allSet() {
		return parameters.allSet();
	}

	@Override
	public void update() {
		notifyObservers();
	}

	@Override
	public void registerObserver(IObserver observer) {
		if(!observers.contains(observer)) {
       	observers.add(observer);	
		}	
	}

	@Override
	public void removeObserver(IObserver observer) {
		if(observers.contains(observer)) {
           observers.remove(observer);            
       }
	}

	@Override
	public void notifyObservers() {
		for(IObserver observer : observers) {
           observer.update();  
		}
	}
	
	/**
	 * To get all parameters of this {@code Scaling}.
	 * @return The parameters
	 */
	public ParameterListScaling getParameters() {
		return parameters;
	}
	
	/**
	 * To get a parameter by it's unique ID.	 
	 * @param parameterID the parameter's ID.
	 * @return The parameter.
	 */
	public Parameter getParameter(String parameterID) {
		return parameters.getParameter(parameterID);
	}
	
	/**
     * To get all parameters of the same type.
     * @param type the parameters' type.
     * @return The parameters.
     */
    public List<ParameterCollectionScaling> getParameters(ParameterType type) {
    	List<ParameterCollectionScaling> result = 
    			new ArrayList<ParameterCollectionScaling>();
    	ParameterCollectionScaling collection = 
    			parameters.getParameterCollection(type);
    	if(collection != null) {
    		result.add(collection);	
    	}
    	return result;
    }
	
}
